package com.sunny.openplatformutils;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.sunny.openplatformutils.utils.JsonUtil;

/**
 * 
 * @author Sunny
 *
 */
public class Alipay {
	private static final String CHARSET = "UTF-8";
	private static AlipayClient alipayClient;
	
	/**
	 * 初始化AlipayClient
	 * 
	 * @param serverUrl		服务地址
	 * @param appId			应用ID
	 * @param publicKey		公钥
	 * @param privateKey	私钥
	 * @param signType		加密类型 RSA/RSA2
	 */
	public static void init(String serverUrl, String appId, String privateKey, String publicKey, String signType) {
		alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, "json", CHARSET, publicKey, signType);
	}
	
	/**
	 * 生成支付宝订单页面
	 * 
	 * @param bizContent		业务请求参数 {@link BizContent}
	 * @param returnUrl			支付状态同步回调地址(可选)
	 * @param notifyUrl			支付状态异步通知地址(可选)
	 * @return					支付页面
	 * @throws Exception
	 */
	public static String pagePay(BizContent bizContent, String returnUrl, String notifyUrl) throws Exception {
		AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
		if (returnUrl != null) {
			alipayRequest.setReturnUrl(returnUrl);
		}
		
		if (notifyUrl != null) {
			alipayRequest.setNotifyUrl(notifyUrl);
		}
		alipayRequest.setBizContent(bizContent.toJson());
		
		AlipayTradePagePayResponse response = alipayClient.pageExecute(alipayRequest);
		return response.isSuccess() ? response.getBody() : response.getMsg();
	}
	
	/**
	 * 根据商户订单号取交易信息
	 * 
	 * @param outTradeNo	商户订单号
	 * @return				交易信息 {@link TradeInfo}
	 * @throws Exception
	 */
	public static TradeInfo queryStatus(String outTradeNo) throws Exception {
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		request.setBizContent(new BizContent(outTradeNo).toJson());
		AlipayTradeQueryResponse res = alipayClient.execute(request);
		
		TradeInfo info = new TradeInfo();
		info.setCode(res.getCode());
		if (res.isSuccess()) {
			info.setStatus(res.getTradeStatus());
			info.setTradeNo(res.getTradeNo());
			info.setOutTradeNo(res.getOutTradeNo());
			info.setBuyerLogonId(res.getBuyerLogonId());
			info.setTotalAmount(Double.parseDouble(res.getTotalAmount()));
			info.setReceiptAmount(Double.parseDouble(res.getReceiptAmount()));
		}
		return info;
	}
	
	public static class BizContent {
		/**
		 * 商户订单号
		 */
		private String out_trade_no;
		/**
		 * 订单金额，单位:元、精确到小数点后两位
		 */
		private Double total_amount;
		/**
		 * 订单标题
		 */
		private String subject;
		/**
		 * 订单描述
		 */
		private String body;
		/**
		 * 原样返回参数,须进行URLEncoder(可选)
		 */
		private String passback_params;
		/**
		 * 销售产品码, 注：目前仅支持FAST_INSTANT_TRADE_PAY
		 */
		private String product_code;
		
		public BizContent() {
		}

		public BizContent(String out_trade_no) {
			this.out_trade_no = out_trade_no;
		}

		public String getOut_trade_no() {
			return out_trade_no;
		}

		public void setOut_trade_no(String out_trade_no) {
			this.out_trade_no = out_trade_no;
		}

		public Double getTotal_amount() {
			return total_amount;
		}

		public void setTotal_amount(Double total_amount) {
			this.total_amount = total_amount;
		}

		public String getSubject() {
			return subject;
		}

		public void setSubject(String subject) {
			this.subject = subject;
		}

		public String getBody() {
			return body;
		}

		public void setBody(String body) {
			this.body = body;
		}

		public String getPassback_params() {
			return passback_params;
		}

		public void setPassback_params(String passback_params) {
			this.passback_params = passback_params;
		}

		public String getProduct_code() {
			return product_code;
		}

		public void setProduct_code(String product_code) {
			this.product_code = product_code;
		}

		public String toJson() throws Exception {
			return JsonUtil.toJson(this);
		}
		
	}
	
	/**
	 * 交易信息
	 * 
	 * @author Sunny
	 *
	 */
	public static class TradeInfo {
		
		/**
		 * 支付状态
		 */
		private TradeStatus status;
		
		/**
		 * 支付宝交易号
		 */
		private String tradeNo;
		
		/**
		 * 商户交易号
		 */
		private String outTradeNo;
		
		/**
		 * 交易的订单金额
		 */
		private double totalAmount;
		
		/**
		 * 实收金额
		 */
		private double receiptAmount;
		
		/**
		 * 商户交易号
		 */
		private String buyerLogonId;
		
		/**
		 * 响应状态码
		 * @see https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105806&docType=1
		 */
		private String code;

		public TradeInfo() {
		}

		public TradeStatus getStatus() {
			return status;
		}

		public void setStatus(TradeStatus status) {
			this.status = status;
		}

		public void setStatus(String status) {
			this.status = TradeStatus.valueOf(status);
		}

		public String getTradeNo() {
			return tradeNo;
		}

		public void setTradeNo(String tradeNo) {
			this.tradeNo = tradeNo;
		}

		public String getOutTradeNo() {
			return outTradeNo;
		}

		public void setOutTradeNo(String outTradeNo) {
			this.outTradeNo = outTradeNo;
		}

		public double getTotalAmount() {
			return totalAmount;
		}

		public void setTotalAmount(double totalAmount) {
			this.totalAmount = totalAmount;
		}

		public double getReceiptAmount() {
			return receiptAmount;
		}

		public void setReceiptAmount(double receiptAmount) {
			this.receiptAmount = receiptAmount;
		}

		public String getBuyerLogonId() {
			return buyerLogonId;
		}

		public void setBuyerLogonId(String buyerLogonId) {
			this.buyerLogonId = buyerLogonId;
		}

		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}
		
	}
	
	/**
	 * 支付状态
	 * 
	 * @author Sunny
	 *
	 */
	public static enum TradeStatus {
		/**
		 * 交易创建，等待买家付款
		 */
		WAIT_BUYER_PAY, 
		/**
		 * 未付款交易超时关闭，或支付完成后全额退款
		 */
		TRADE_CLOSED,
		/**
		 * 交易支付成功
		 */
		TRADE_SUCCESS,
		/**
		 * 交易结束，不可退款
		 */
		TRADE_FINISHED
		
	}
}
